package com.ssd.sync.impl;

import com.ssd.sync.SyncManager;
import com.ssd.sync.SyncThread;
import com.ssd.sync.properties.RedisSyncProperties;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;


/**
 * Redis同步管理器实现类
 * 负责启动和管理数据同步线程
 */
@Slf4j
@Component
public class SyncManagerImpl implements SyncManager {

    // 默认的线程池用于执行同步任务
    private static final ThreadPoolTaskExecutor DEFAULT_SYNC_EXECUTOR;

    // Redis模板用于操作Redis
    @Resource
    private RedisTemplate redisTemplate;
    // Redisson客户端用于分布式锁等特性
    @Resource
    private RedissonClient redissonClient;
    // Redis同步属性配置
    @Resource
    private RedisSyncProperties redisSyncProperties;

    // 静态代码块用于初始化默认的线程池
    static {
        DEFAULT_SYNC_EXECUTOR = new ThreadPoolTaskExecutor();
        DEFAULT_SYNC_EXECUTOR.setCorePoolSize(10);
        DEFAULT_SYNC_EXECUTOR.setMaxPoolSize(20);
        DEFAULT_SYNC_EXECUTOR.setQueueCapacity(999);
        DEFAULT_SYNC_EXECUTOR.setThreadNamePrefix("redis-queue-sync-");
        // 设置拒绝策略：当pool已经达到max size的时候，如何处理新任务
        // CALLER_RUNS：不在新线程中执行任务，而是有调用者所在的线程来执行
        DEFAULT_SYNC_EXECUTOR.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        DEFAULT_SYNC_EXECUTOR.initialize();
    }

    /**
     * 启动数据同步任务
     * @param queueName 队列名称
     * @param storageType 存储类型
     * @param mode 同步模式
     */
    @Override
    public void start(String queueName, int storageType, int mode) {
        this.start(queueName, storageType, mode, DEFAULT_SYNC_EXECUTOR);
    }

    /**
     * 启动数据同步任务
     * @param queueName 队列名称
     * @param storageType 存储类型
     * @param mode 同步模式
     * @param dataSyncExecutor 用于执行同步任务的线程池
     */
    @Override
    public void start(String queueName, int storageType, int mode, final Executor dataSyncExecutor) {
        //根据队列的数量循环，将每个队列的数据同步任务提交到线程池
        for (int index = 0; index < redisSyncProperties.getQueueNum(); index++) {
            try {
                // 根据传入的dataSyncExecutor决定使用默认线程池还是自定义线程池
                if (dataSyncExecutor == null) {//使用默认线程池
                    //使用getSyncThread方法获取任务对象
                    DEFAULT_SYNC_EXECUTOR.execute(getSyncThread(queueName, index, storageType, mode));
                } else {//使用自定义线程池
                    dataSyncExecutor.execute(getSyncThread(queueName, index, storageType, mode));
                }
            } catch (Exception e) {
                log.error("同步数据处理异常，e:", e);
            }
        }
    }

    /**
     * 根据存储类型获取对应的同步线程实例
     * @param queueName 队列名称
     * @param index 队列索引
     * @param storageType 存储类型
     * @param mode 同步模式
     * @return 同步线程实例
     */
    private SyncThread getSyncThread(String queueName, int index, Integer storageType, int mode) {
        // 根据不同的存储类型返回对应的同步线程实例
        switch (storageType) {
            case 1://hash
                return new HashSyncThread(redissonClient, queueName, index, redisTemplate, redisSyncProperties.getPerCount(), mode);
            case 2://list
                return null;
            case 3:// zset
                return null;
        }
        return null;
    }


}

